<?php
namespace Api;
use Kuyuan\WqCore\api\Api;
use Kuyuan\WqCore\util\DB;
use Kuyuan\WqCore\util\Util;
use Yansongda\Pay\Exceptions\Exception;
use Yansongda\Pay\Pay;

/**
 * 开红包
 * Class SendRed
 * @package Api
 */
class Open extends Api
{
    private $Red = null;

    // 当前用户uid
    private $_uid = 0;
    // 红包id
    private $_red_id = 0;
    // 分享id
    private $_share_id = '';
    // 红包信息
    private $_red = 0;
    // 财务参数
    private $_setting_finance = [];

    public function __construct()
    {
        parent::__construct();
        $this->Red = $this->newController("Red");
        $this->_uid = $this->Red->getUid();
        $this->_red_id = $this->_gpc["red_id"];
        $this->_share_id = $this->_gpc["share_id"];
    }

    /**
     * 开红包
     * @throws \Exception
     */
    public function index()
    {
        Util::appointPost();
        DB::begin();
        try {
            // 1、获取红包信息
            $this->getRed();

            // 1.1、红包地区限制
            if($this->_red["area_type"] != 0) {
                $_area = implode('/',$this->_gpc['area']);
                if(strpos($_area,$this->_red["area"]) === false) {
                    throw new \PDOException("仅支持".$this->_red["area"]."的用户开红包",100);
                }
            }

            // 2、验证红包状态
            $_check_status = $this->checkStatus();
            if($_check_status !== true) {
                throw new \PDOException($_check_status["err_msg"],$_check_status["code"]);
            }

            // 3、验证红包开始(结束)时间
            if($this->_red["time_type"] == 2) {
                $_check_time = $this->checkTime();
                if($_check_time !== true) {
                    throw new \PDOException($_check_time["err_msg"],$_check_time["code"]);
                }
            }

            // 4、验证红包数量
            if($this->Red->numbered($this->_red_id) >= $this->_red["number"]) {
                throw new \PDOException("您来晚了，红包已被抢完",1074);
            }

            // 5、验证当前用户是否开启过红包
            if($this->alreadyOpen()) {
                throw new \PDOException("您已经开过此红包了",1075);
            }

            // 6、发送卡券，新增用户卡券
            if($this->_red["send_coupon"]) {
                $MemberCoupon = $this->newController("MemberCoupon");
                $MemberCoupon->add(array(
                    "red_id" => $this->_red_id,
                    "coupon_id" => $this->_red["coupon"]
                ));
            }

            // 7、新增用户余额
                // 获取财务相关参数
                $SettingFinance = $this->newController("SettingFinance");
                $this->_setting_finance = $SettingFinance->find();
                // 是否分享助力红包
                $_is_share = false;
                // 分享红包金额目标
                $_share_to_go = 1;
                // 开红包用户金额目标
                $_user_to_go = 1;
            $Member = $this->newController("Member");
            $_money = $this->getMoney();
            // 7.1、是否开启助力红包，分享红包金额给分享者
            if($this->_red["award"] == 1 && $this->_share_id) {
                $_share = $this->getShare();
                // 1、分享id数据存在
                // 2、分享用户id不等于当前用户id
                // 3、红包所属用户uid不等于当前用户uid
                if($_share
                    &&
                   $_share["uid"] != $this->_uid
                    &&
                    $this->_red["uid"] != $this->_uid
                ) {
                    $_money_info = $this->getAwardMoney($_money);
                    if($_money_info) {
                        $_is_share = true;
                        $_money = $_money_info["money"];
                        $_award_money = $_money_info["award"];
                        // 分享者奖励
                        // 判断是否直接到微信钱包
                        if($this->testDeposit($_award_money)) {
                            if (!$this->deposit($_award_money,true)){
                                $Member->financeHandle($_award_money,true,$_share["uid"]);
                            } else {
                                $_share_to_go = 2;
                            }
                        } else {
                            $Member->financeHandle($_award_money,true,$_share["uid"]);
                        }
                    }
                }
            }

            // 7.1、新增用户余额
            if($this->testDeposit($_money)) {
                if (!$this->deposit($_money,false)){
                    $Member->financeHandle($_money,true);
                } else {
                    $_user_to_go = 2;
                }
            } else {
                $Member->financeHandle($_money,true);
            }

            // 8、新增红包记录
            $RedRecord = $this->newController("RedRecord");
            $_record_id = $RedRecord->add(array(
                "money" => $_money,
                "red_id" => $this->_red_id,
                "to_go" => $_user_to_go
            ));
            // 新增红包助力奖励记录
            if($_is_share) {
                $RedRecord->add(
                    array(
                        "money" => $_award_money,
                        "red_id" => $this->_red_id,
                        "pid" => $_record_id,
                        "to_go" => $_share_to_go
                    ),
                    $_share["uid"]
                );
            }

            // 9、新增红包开启数量
            $this->Red->addNumbered($this->_red_id);

            DB::commit();

            // end:成功返回，红包信息
            $_result_data = array(
                "money"=>$_money
            );
            if($this->_red["send_coupon"]) {
                $_result_data["coupon_id"] = $this->_red["coupon"];
            }
            $_result = array(
                "code"=>0,
                "data"=>$_result_data
            );
            Util::returns($_result);
        } catch (\PDOException $e) {
            DB::back();
            $_result = array("code"=>$e->getCode(),"err_msg"=>$e->getMessage());
            Util::returns($_result);
        }
    }

    /**
     * 获取红包信息
     */
    private function getRed()
    {
        $this->_red = $this->Red->take($this->_red_id);
    }

    /**
     * 验证红包状态
     */
    private function checkStatus()
    {
        $_result = true;
        if($this->_red["status"] != 2) {
            switch($this->_red["status"]) {
                case 4:
                    $_result = array("code"=>1071,"err_msg"=>"红包已停止");
                    break;
                case 9:
                    $_result = array("code"=>1072,"err_msg"=>"红包已删除");
                    break;
                default:
                    $_result = array("code"=>1073,"err_msg"=>"未知错误");
            }
            return $_result;
        }
        return $_result;
    }

    /**
     * 验证红包开始结束时间
     */
    private function checkTime()
    {
        $_result = true;
        if(TIMESTAMP < $this->_red["start_time"]) {
            $_result = array("code"=>1076,"err_msg"=>"红包正在准备中");
        } else if(TIMESTAMP > $this->_red["end_time"]) {
            $_result = array("code"=>1077,"err_msg"=>"红包已过期");
        }
        return $_result;
    }

    /**
     * 验证是否开过红包
     */
    private function alreadyOpen()
    {
        $RedRecord = $this->newController("RedRecord");
        return $RedRecord->take($this->_red_id);
    }

    /**
     * 获取红包金额
     */
    private function getMoney()
    {
        if($this->_red["type"] == 1) {
            // 普通红包
            return $this->_red["money"];
        } else {
            // 随机手气红包
            return $this->randomMoney();
        }
    }

    /**
     * 获取手气红包随机金额
     */
    private function randomMoney()
    {
        // 红包剩余金额
        $_surplus_money = $this->Red->surplus($this->_red_id);
        // 红包剩余数量
        $_surplus_number = $this->_red["number"] - $this->Red->numbered($this->_red_id);

        // 0、判断是不是最后一个红包
        if($_surplus_number == 1) {
            // 是最后一个红包
            // 1.1、如果是最后一个将剩余红包金额都返回
            $_money = $_surplus_money;
        } else {
            // 2.0、否则算出一个随机金额
            // 2.1、红包剩余总金额/红包剩余数量
            $_average = $_surplus_money / $_surplus_number;
            // 2.2、算出红包随机金额最大值
            // 2.3、算出红包随机金额最小值
            $_min = 0.01;
            // 2.4、随机出最小值到最大值的随机金额
            $_money = $_min + mt_rand() / mt_getrandmax() * ($_average - $_min);
            $_money = sprintf("%.2f",$_money);
        }
        return $_money;
    }

    /**
     * 获取分享信息
     */
    private function getShare()
    {
        $Share = $this->newController("Share");
        return $Share->find($this->_share_id);
    }

    /**
     * 计算分享奖励金额
     * @param double $_red_money 红包开到的金额
     * @return bool
     */
    private function getAwardMoney($_red_money)
    {
        $_money = false;
        $Setting = $this->newController("Setting");
        $_setting = $Setting->find();
        $_share_ratio = (int) $_setting["share_ratio"];
        unset($Setting,$_setting);
        if($_share_ratio) {
            $_share_ratio = round($_share_ratio / 100,2);
            $_award_money =$_red_money * $_share_ratio;
            if($_award_money >= 0.01) {
                $_money = array("money"=>$_red_money-$_award_money,"award"=>$_award_money);
            } else if($_award_money < 0.01 && (($_red_money - 0.01) >= 0.01)) {
                $_award_money = 0.01;
                $_money = array("money"=>$_red_money-$_award_money,"award"=>$_award_money);
            }
        }
        return $_money;
    }

    /**
     * 判断是否直接到账
     * @param $_money
     * @return mixed
     */
    private function testDeposit($_money)
    {
        if($this->_setting_finance["deposit_check"] <= 0 || $_money >= $this->_setting_finance["deposit_check"]) {
            return false;
        }
        if($_money < $this->_setting_finance["low_deposit"]) {
            return false;
        }
        return true;
    }

    /**
     * 直接提现到用户微信钱包
     * @param double $_money 金额
     * @param boolean $_share_award 是否为分享奖励
     * @return mixed
     */
    private function deposit($_money,$_share_award)
    {
        $Setting = $this->newController("Setting");
        $_setting = $Setting->find();
        $_pay_config = \Kuyuan\WqCore\wx\Pay::config(false);
        \Kuyuan\WqCore\wx\Pay::getCertKey($_pay_config["cert_client"],$_pay_config["cert_key"]);
        $Member = $this->newController("Member");
        try{
            $_pay_result = Pay::wechat($_pay_config)->transfer(array(
                "partner_trade_no"=>TIMESTAMP.mt_rand(10000,99999),
                "openid" => $Member->uidToOpenid(),
                'check_name' => 'NO_CHECK',
                'amount' => $_money * 100,
                'desc' => $_share_award ? $_setting["app_name"]."-您的朋友帮您到的红包哦" : $_setting["app_name"]."-红包到账"
            ));
            if($_pay_result->return_code != "SUCCESS" || $_pay_result->result_code != "SUCCESS") {
                throw new \PDOException("未知错误",708);
            }
            \Kuyuan\WqCore\wx\Pay::clearCertKey($_pay_config["cert_client"],$_pay_config["cert_key"]);
            return true;
        } catch (Exception $e) {
            \Kuyuan\WqCore\wx\Pay::clearCertKey($_pay_config["cert_client"],$_pay_config["cert_key"]);
            return false;
        }
    }
}